package extended

import (
	"go_gvm_mini/instructions/base"
	"go_gvm_mini/instructions/loads"
	"go_gvm_mini/instructions/math"
	"go_gvm_mini/instructions/store"
	"go_gvm_mini/rtda"
)

// WIDE Extend local variable index by additional bytes
type WIDE struct {
	modifiedInstruction base.Instruction
}

func (w *WIDE) FetchOperands(reader *base.ByteCodeReader) {
	opcode := reader.ReadUInt8()
	switch opcode {
	case 0x15:
		inst := &loads.ILOAD{}
		inst.Index = uint(reader.ReadUInt16())
		w.modifiedInstruction = inst
	case 0x16:
		inst := &loads.LLOAD{}
		inst.Index = uint(reader.ReadUInt16())
		w.modifiedInstruction = inst
	case 0x17:
		inst := &loads.FLOAD{}
		inst.Index = uint(reader.ReadUInt16())
		w.modifiedInstruction = inst
	case 0x18:
		inst := &loads.DLOAD{}
		inst.Index = uint(reader.ReadUInt16())
		w.modifiedInstruction = inst
	case 0x19:
		inst := &loads.ALOAD{}
		inst.Index = uint(reader.ReadUInt16())
		w.modifiedInstruction = inst
	case 0x36:
		inst := &store.ISTORE{}
		inst.Index = uint(reader.ReadUInt16())
		w.modifiedInstruction = inst
	case 0x37:
		inst := &store.LSTORE{}
		inst.Index = uint(reader.ReadUInt16())
		w.modifiedInstruction = inst
	case 0x38:
		inst := &store.FSTORE{}
		inst.Index = uint(reader.ReadUInt16())
		w.modifiedInstruction = inst
	case 0x39:
		inst := &store.DSTORE{}
		inst.Index = uint(reader.ReadUInt16())
		w.modifiedInstruction = inst
	case 0x3a:
		inst := &store.ASTORE{}
		inst.Index = uint(reader.ReadUInt16())
		w.modifiedInstruction = inst
	case 0x84:
		inst := &math.IINCR{}
		inst.Index = uint(reader.ReadUInt16())
		inst.Const = int32(reader.ReadInt16())
		w.modifiedInstruction = inst
	case 0xa9: // ret
		panic("Unsupported opcode: 0xa9!")
	}
}

func (w *WIDE) Execute(jFrame *rtda.JFrame) {
	w.modifiedInstruction.Execute(jFrame)
}
